home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 February: Tool Chest / Dev.CD Feb 99 TC.toast / What's New? / Development Kits / Mac OS USB v1.1f3 DDK / Examples / KeyboardModule / KBDHIDEmulation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-07  |  7.4 KB  |  276 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        KBDHIDEmulation.c
  3.  
  4.     Contains:    Keyboard Emulation code
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8. */
  9.  
  10. #include <Types.h>
  11. #include <Devices.h>
  12. #include <DriverServices.h>
  13. #include <USB.h>
  14.  
  15. #ifndef DDKBuild
  16. #include <USBPriv.h>
  17. #endif
  18.  
  19. #include "KeyboardModule.h"
  20.  
  21. extern    usbKeyboardPBStruct myKeyboardPB;
  22. extern    usbKeyboardPBStruct shimKeyboardPB;
  23.  
  24. void GetKeysPressed(USBHIDData * pKeysPressed);
  25.  
  26. OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon)
  27. {
  28.     myKeyboardPB.interruptRefcon = refcon;
  29.     myKeyboardPB.pSHIMInterruptRoutine = HIDInterruptFunction;
  30.     return 0;
  31. }
  32.  
  33. OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
  34. {
  35.     switch (theControlSelector)
  36.     {
  37.         case kHIDSetLEDStateByBits:
  38.             shimKeyboardPB.hidReport[0] = *(UInt8*)theControlData;
  39.  
  40.             shimKeyboardPB.retryCount = kKeyboardRetryCount;
  41.             shimKeyboardPB.delayLevel = 0;                            
  42.             shimKeyboardPB.transDepth = 0;    
  43.             
  44.             shimKeyboardPB.pb.usbRefcon = kSetKeyboardLEDs;                    /* Start with setting the interface protocol */
  45.             KeyboardInitiateTransaction(&shimKeyboardPB.pb);
  46.             break;
  47.             
  48.         case kHIDRemoveInterruptHandler:
  49.             myKeyboardPB.interruptRefcon = nil;
  50.             myKeyboardPB.pSavedInterruptRoutine = nil;
  51.             myKeyboardPB.pSHIMInterruptRoutine = nil;
  52.             break;
  53.             
  54.         case kHIDEnableDemoMode:
  55.             USBExpertStatus(myKeyboardPB.interfaceRef, "\pUSBHIDKeyboardModule: Demo Mode Enabled", myKeyboardPB.interfaceRef);
  56.             myKeyboardPB.pSavedInterruptRoutine = myKeyboardPB.pSHIMInterruptRoutine;
  57.             myKeyboardPB.pSHIMInterruptRoutine = USBDemoKeyIn;
  58.             break;
  59.  
  60.         case kHIDDisableDemoMode:
  61.             USBExpertStatus(myKeyboardPB.interfaceRef, "\pUSBHIDKeyboardModule: Demo Mode Disabled", myKeyboardPB.interfaceRef);
  62.             myKeyboardPB.pSHIMInterruptRoutine = myKeyboardPB.pSavedInterruptRoutine;
  63.             break;
  64.  
  65.         default:
  66.             return paramErr;
  67.     }
  68.     return 0;
  69. }
  70.  
  71. void GetKeysPressed(USBHIDDataPtr pKeysPressed)
  72. {
  73. UInt8    i,keycount;
  74.     
  75.     keycount = 0;
  76.     for (i = 0; i < kKeyboardModifierBits; i++)
  77.     {
  78.         if (myKeyboardPB.oldHIDReport[0] & (1 << i))
  79.         {
  80.             pKeysPressed->kbd.usbkeycode[keycount++] = (0xe0 + i);
  81.         }
  82.     }
  83.             
  84.     if ((myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] == 0) || (myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] > 0x03))
  85.     {
  86.         for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  87.         {
  88.             if (myKeyboardPB.oldHIDReport[i] > 0x03)
  89.             {
  90.                 pKeysPressed->kbd.usbkeycode[keycount++] = myKeyboardPB.oldHIDReport[i];
  91.             }
  92.         }                                                        
  93.     }
  94.     pKeysPressed->kbd.keycount = keycount;
  95. }
  96.  
  97.  
  98. OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
  99. {
  100. HIDInterruptProcPtr * pHIDIntProcPtr;
  101. UInt32 * pInterruptRefcon;
  102.  
  103.     switch (theInfoSelector)
  104.     {
  105.         case kHIDGetCurrentKeys:
  106.             GetKeysPressed((USBHIDDataPtr)theInfo);
  107.             break;
  108.  
  109.         case kHIDGetInterruptHandler:
  110.             pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;  
  111.             *pHIDIntProcPtr = myKeyboardPB.pSHIMInterruptRoutine;
  112.             break;
  113.  
  114.         case kHIDGetInterruptRefcon:
  115.             pInterruptRefcon = (UInt32 *)theInfo;
  116.             *pInterruptRefcon = myKeyboardPB.interruptRefcon;
  117.             break;
  118.         
  119.         default:
  120.             return paramErr;
  121.     }
  122.     return 0;
  123. }
  124.  
  125. OSStatus USBHIDPollDevice(void)
  126. {
  127. #ifndef DDKBuild
  128.     USLPolledProcessDoneQueue();
  129. #endif
  130.     return kUSBNoErr;
  131. }
  132.  
  133. OSStatus USBHIDEnterPolledMode(void)
  134. {    
  135.     return unimpErr;
  136. }
  137.  
  138. OSStatus USBHIDExitPolledMode(void)
  139. {
  140.     return unimpErr;
  141. }
  142.  
  143. void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
  144. {
  145. #pragma unused (devicetype)
  146.  
  147. UInt8    i, j, newkey, oldkey, deltas;
  148.  
  149. UInt8        changedmodifiers, keycount;
  150. USBHIDData    theKeyboardData;
  151. Boolean        keypressedflag, keyreleasedflag;
  152.     
  153.     deltas = 0;
  154.     
  155.     if (myKeyboardPB.hidEmulationInit == false)
  156.     {
  157.         myKeyboardPB.hidEmulationInit = true;
  158.         for (i = 0; i < kKeyboardReportSize; i++)
  159.             myKeyboardPB.oldHIDReport[i] = 0;
  160.     };
  161.     
  162.     myKeyboardPB.oldHIDReport[1] = 0x0;
  163.     hidReport[1] = 0x0;
  164.     
  165.     for (i = 0; i < kKeyboardReportSize; i++)
  166.     {
  167.         if (hidReport[i] != myKeyboardPB.oldHIDReport[i])
  168.         {
  169.             deltas++;
  170.         }
  171.     }
  172.     
  173.     if ((myKeyboardPB.sendRawReportFlag) && deltas)
  174.     {
  175.         (*myKeyboardPB.pSHIMInterruptRoutine)(0xff, (void *)&hidReport[0]);
  176.     }
  177.     else
  178.     {
  179.         if (deltas)
  180.         {
  181.             keycount = 0;
  182.             changedmodifiers = hidReport[0] ^  myKeyboardPB.oldHIDReport[0];
  183.             
  184.             if (changedmodifiers)
  185.             {
  186.                 for (i = 0; i < kKeyboardModifierBits; i++)
  187.                 {
  188.                     if (changedmodifiers & (1 << i))
  189.                     {
  190.                         if (hidReport[0] & (1 << i))
  191.                         {
  192.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0xe0 + i);
  193.                         }
  194.                         else
  195.                         {
  196.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0x80e0 + i);
  197.                         }
  198.                     }
  199.                 }
  200.                 myKeyboardPB.oldHIDReport[0] = hidReport[0];
  201.             }
  202.             
  203.             if ((hidReport[kKeyboardOffsetToKeys] == 0) || (hidReport[kKeyboardOffsetToKeys] > 0x03))
  204.             {
  205.                 // While this double loop may look strange, I refer you to appendix C, of the HID Devices specification.
  206.                 // pp. 73 & 74 clearly state that report order is abitrary and does not reflect the order of events.
  207.                 // to quote: "The order of keycodes in array fields has no significance.  Order determination is done
  208.                 // by the host software comparing the contents of the previous report to the current report.  If two or 
  209.                 // more keys are pressed in one report, their order is indeterminate.  Keyboards may buffer events that
  210.                 // would have otherwise resulted in multiple events in a single report".
  211.                 
  212.                 // Because this specification (or lack thereof) states that the order is indeterminant, we have to 
  213.                 // check all the old keys against all the new keys...
  214.                 
  215.                 for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  216.                 {
  217.                     keypressedflag = true;
  218.                     newkey = hidReport[i];
  219.                     
  220.                     keyreleasedflag = true;
  221.                     oldkey = myKeyboardPB.oldHIDReport[i];                            
  222.                     for (j = kKeyboardOffsetToKeys; j < (kKeyboardOffsetToKeys + kKeyboardReportKeys); j++)                                // then look through all the keys that were previously and are currently reported as pressed
  223.                     {                                    
  224.                         if (newkey == myKeyboardPB.oldHIDReport[j])        // was this new key already pressed?
  225.                         {                                
  226.                             keypressedflag = false;                        // if it was, then don't report it as being pressed.
  227.                         }
  228.                         
  229.                         if (oldkey == hidReport[j])                        // Is the old key still pressed?
  230.                         {                                
  231.                             keyreleasedflag = false;                    // If yes, then don't report it as being released
  232.                         }
  233.                     }
  234.                     if ((newkey > 0x03) && keypressedflag)
  235.                     {
  236.                         theKeyboardData.kbd.usbkeycode[keycount++] = newkey;
  237.                     }
  238.                     
  239.                     if ((oldkey > 0x03) && keyreleasedflag)
  240.                     {
  241.                         theKeyboardData.kbd.usbkeycode[keycount++] = (oldkey + 0x8000);
  242.                     }
  243.                     
  244.                     if (keycount > 20)                                    // a worse case scenario is:
  245.                     {                                                    // 4 modifier keys up
  246.                         break;                                            // the other 4 modifier keys down
  247.                     }                                                    // 6 previously reported keys up
  248.                 }                                                        // 6 newly reported keys down
  249.                                                                         // 6 + 6 + 4 + 4 = 20
  250.                 for (i = 0; i<kKeyboardReportSize; i++)
  251.                 {
  252.                     myKeyboardPB.oldHIDReport[i] = hidReport[i];
  253.                 };
  254.             }
  255.             
  256.             if ((myKeyboardPB.pSHIMInterruptRoutine) && keycount)
  257.             {
  258.                 theKeyboardData.kbd.keycount = keycount;
  259.                 (*myKeyboardPB.pSHIMInterruptRoutine)(myKeyboardPB.interruptRefcon, (void *)&theKeyboardData);
  260.             }
  261.         }
  262.     }
  263. }
  264.  
  265.  
  266. USBHIDModuleDispatchTable TheHIDModuleDispatchTable =
  267. {
  268.     (UInt32)0,
  269.     (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt,
  270.     (USBHIDPollDeviceProcPtr)USBHIDPollDevice,
  271.     (USBHIDControlDeviceProcPtr)USBHIDControlDevice,
  272.     (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo,
  273.     (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode,
  274.     (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode,
  275. };
  276.